package com.gs.process.core.server;

import com.alibaba.fastjson.JSON;
import com.gs.process.core.handler.ProcessFinishedHandler;
import com.gs.process.core.handler.ProcessHandlerService;
import com.gs.process.model.Approval;
import com.gs.process.model.ApprovalDetails;
import com.gs.process.model.dto.ApprovalDto;
import com.gs.process.model.dto.Constant;
import com.gs.process.model.dto.TableFieldCondition;
import com.shallowUniverse.model.Result;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.springframework.util.ObjectUtils;

import java.util.Map;

/**
 * @author Shuai Guo
 * @version 1.0
 * @description
 * @date 2021/8/3
 */
public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    private final ProcessHandlerService processHandlerService;
    private final QueryRunner runner;

    public HttpHandler(ProcessHandlerService processHandlerService, QueryRunner runner) {
        this.processHandlerService = processHandlerService;
        this.runner = runner;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
        //获取请求体
        String content = msg.content().toString(CharsetUtil.UTF_8);
        //判断是否为空
        if (ObjectUtils.isEmpty(content)) {
            return;
        }

        //获取请求地址
        String uri = msg.uri();
        if (uri.contains("handle")) {
            //转换为对象
            ApprovalDto approvalDto = JSON.parseObject(content, ApprovalDto.class);
            Approval approval = approvalDto.getApproval();
            ApprovalDetails approvalDetails = approvalDto.getApprovalDetails();
            //获取处理器
            ProcessFinishedHandler processFinishedHandler = processHandlerService.generateHandler(approval.getTarget());
            //判断是否为空
            if (!ObjectUtils.isEmpty(processFinishedHandler)) {
                //查询原始数据
                String sql = String.format("select * from %s where %s = %s", approval.getTarget(), approval.getPrimaryKey(), approval.getTargetId());
                Map<String, Object> data = this.runner.query(sql, new MapHandler());
                //转换数据为json
                String json = JSON.toJSONString(data);
                //判断是同意还是拒绝
                if (Constant.PROCESS_ALLOW_SIGN.equals(approval.getStatus())) {
                    processFinishedHandler.postAllowHandle(json, approvalDetails);
                } else {
                    processFinishedHandler.postRefuseHandle(json, approvalDetails);
                }

                this.writeResponse(ctx, null);
            }
        } else {
            //解析请求体获取请求参数
            TableFieldCondition tableFieldCondition = JSON.parseObject(content, TableFieldCondition.class);
            //定义sql语句
            String sql = String.format("select %s from %s where %s = %s", tableFieldCondition.getColumn(), tableFieldCondition.getTable(), tableFieldCondition.getPrimaryKey(), tableFieldCondition.getId());
            //查询结果
            String value = runner.query(sql, new ScalarHandler<>());

            //写回返回值
            this.writeResponse(ctx, value);
        }
    }

    private void writeResponse(ChannelHandlerContext ctx, Object body) {
        //定义结果对象
        Result<Object> result = new Result<>();
        result.setBody(body);
        result.setCode(200);
        //定义返回值
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK,
                Unpooled.wrappedBuffer(JSON.toJSONString(result).getBytes()));

        HttpHeaders heads = response.headers();
        heads.add(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=UTF-8");
        heads.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        heads.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);

        ctx.writeAndFlush(response);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelReadComplete");
        super.channelReadComplete(ctx);
        ctx.flush(); // 4
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("exceptionCaught");
        if (null != cause) {
            cause.printStackTrace();
        }
        if (null != ctx) {
            ctx.close();
        }
    }
}
